--[[
* MapLib 2.0
* File: <AddOn>\MapLib\MapLib_ChatHandler.lua
* $Revision: 154 $
* $Date: 2007-01-25 12:27:42 +0000 (Thu, 25 Jan 2007) $
* 
* Copyright (c) 2006-2007, Mery (Moritz Metelmann)
* All rights reserved.
* 
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* 
*    * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
*    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
*    * Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
]]--

local vmajor, vminor = "MapLib-2.0", tonumber(string.sub("$Revision: 154 $", 12, -3))

-- Version check: Only one major instance of MapLib can be installed, if another already is: abort.
if (MapLib and MapLib.ChatHandler and (MapLib.ChatHandler.vmajor ~= vmajor or MapLib.ChatHandler.vminor >= vminor)) then return; end;

if (not MapLib) then MapLib = {}; end;
if (not MapLib.ChatHandler) then MapLib.ChatHandler = {}; end;

MapLib.ChatHandler.vmajor = vmajor;
MapLib.ChatHandler.vminor = vminor;

local L = MapLib.Localization;
MapLib.ChatHandler.registeredCommands = {};
DEFAULT = { "ChatFrame1" };

CHAT_MSG_MAPNOTES = "MapNotes";
ChatTypeGroup["MAPNOTES"] = {
	"CHAT_MSG_MAPNOTES"
};
ChatTypeInfo["MAPNOTES"] = { sticky = 0 };
tinsert(OtherMenuChatTypeGroups, 4, "MAPNOTES");
ChatTypeInfo["MAPNOTES"].r = 1;
ChatTypeInfo["MAPNOTES"].g = 1;
ChatTypeInfo["MAPNOTES"].b = 1;
ChatTypeInfo["MAPNOTES"].id = MapLib.CHATFRAME_ID;

MapLib.ChatHandler.After_FCF_Tab_OnClick = function(button)
	if ( button == "RightButton" ) then
		local frameName = "ChatFrame" .. this:GetID();
		local activeFrames;
		if ( MapLibSavedPerCharacter.ChatHandler.Frames[UnitName("player")] ) then
			activeFrames = MapLibSavedPerCharacter.ChatHandler.Frames[UnitName("player")];
		else
			activeFrames = MapLib.ChatHandler.DEFAULT;
		end;
		for _, frameName in pairs(activeFrames) do
			if ( frameName == "ChatFrame" .. this:GetID() ) then
				tinsert(getglobal(frameName).messageTypeList, "MAPNOTES");
			end
		end
	end
end;

MapLib.ChatHandler.After_FCFMessageTypeDropDown_OnClick = function()
	if ( not MapLibSavedPerCharacter.ChatHandler.Frames[UnitName("player")] ) then
		MapLibSavedPerCharacter.ChatHandler.Frames[UnitName("player")] = MapLib.ChatHandler.DEFAULT;
	end
	if ( this.value == "MAPNOTES" ) then
		local frameName = FCF_GetCurrentChatFrame():GetName();
		if ( UIDropDownMenuButton_GetChecked() ) then
			for i, activeFrame in pairs(MapLibSavedPerCharacter.ChatHandler.Frames[UnitName("player")]) do
				if ( activeFrame == frameName ) then
					tremove(MapLibSavedPerCharacter.ChatHandler.Frames[UnitName("player")], i);
				end
			end
		else
			tinsert(MapLibSavedPerCharacter.ChatHandler.Frames[UnitName("player")], frameName);
		end
	end
end;

MapLib.ChatHandler.After_FCF_CancelFontColorSettings = function(previousValues)
	if ( previousValues.r and UIDROPDOWNMENU_MENU_VALUE == "MAPNOTES" ) then
		MapLibSavedPerCharacter.ChatHandler.Color[UnitName("player")] = { r=previousValues.r, g=previousValues.g, b=previousValues.b };
    ChatTypeInfo["MAPNOTES"].r = previousValues.r;
    ChatTypeInfo["MAPNOTES"].g = previousValues.g;
    ChatTypeInfo["MAPNOTES"].b = previousValues.b;
		for i = 1, NUM_CHAT_WINDOWS, 1 do 
    	getglobal("ChatFrame"..i):UpdateColorByID(MapLib.CHATFRAME_ID, previousValues.r, previousValues.g, previousValues.b);
    end;
	end;
end;

MapLib.ChatHandler.After_FCF_SetChatTypeColor = function()
	if (UIDROPDOWNMENU_MENU_VALUE == "MAPNOTES") then
		local r,g,b = ColorPickerFrame:GetColorRGB();
		MapLibSavedPerCharacter.ChatHandler.Color[UnitName("player")] = { r=r, g=g, b=b };
    ChatTypeInfo["MAPNOTES"].r = r;
    ChatTypeInfo["MAPNOTES"].g = g;
    ChatTypeInfo["MAPNOTES"].b = b;
		for i = 1, NUM_CHAT_WINDOWS, 1 do 
    	getglobal("ChatFrame"..i):UpdateColorByID(MapLib.CHATFRAME_ID, r, g, b);
    end;
	end;
end;

Sea.util.hook("FCF_Tab_OnClick", "MapLib.ChatHandler.After_FCF_Tab_OnClick", "after");
Sea.util.hook("FCFMessageTypeDropDown_OnClick", "MapLib.ChatHandler.After_FCFMessageTypeDropDown_OnClick", "after");
Sea.util.hook("FCF_SetChatTypeColor", "MapLib.ChatHandler.After_FCF_SetChatTypeColor", "after");
Sea.util.hook("FCF_CancelFontColorSettings", "MapLib.ChatHandler.After_FCF_CancelFontColorSettings", "after");

MapLib.ChatHandler.PrintToChat = function(msg, color)
	if (not color) then 
		color = MapLibSavedPerCharacter.ChatHandler.Color[UnitName("player")] or MapLib.CHATFRAME_DEFAULTCOLOR;
	end;
	msg = L["[MapNotes]: "]..msg;
	local chatFrames = MapLibSavedPerCharacter.ChatHandler.Frames[UnitName("player")] or MapLib.ChatHandler.DEFAULT;
	for _, chatFrame in pairs(chatFrames) do
		local chatFrameX = getglobal(chatFrame);
		if (chatFrameX) then
			chatFrameX:AddMessage(msg, color.r, color.g, color.b, MapLib.CHATFRAME_ID);
		end;
	end;
end

MapLib.ChatHandler.VariablesLoaded = function()
	if (not MapLibSavedPerCharacter) then MapLibSavedPerCharacter = {}; end;
	if (not MapLibSavedPerCharacter.ChatHandler) then MapLibSavedPerCharacter.ChatHandler = {}; end;
	if (not MapLibSavedPerCharacter.ChatHandler.Color) then MapLibSavedPerCharacter.ChatHandler.Color = {}; end;
	if (not MapLibSavedPerCharacter.ChatHandler.Frames) then MapLibSavedPerCharacter.ChatHandler.Frames = {}; end;
	local color = MapLibSavedPerCharacter.ChatHandler.Color[UnitName("player")] or MapLib.CHATFRAME_DEFAULTCOLOR;
	ChatTypeInfo["MAPNOTES"].r = color.r;
  ChatTypeInfo["MAPNOTES"].g = color.g;
  ChatTypeInfo["MAPNOTES"].b = color.b;
	
	MapLib.ChatHandler.RegisterSlashCommand(L["help"], MapLib.ChatHandler.PrintHelp, L[" - Prints this list."]);
	MapLib.ChatHandler.RegisterSlashCommand(L["show"], MapLib.ToggleMap, L[" - Toggles the MapNotes map."]);
end;

--[[
 * This function is a slight modification of the tokenizer found
 * on http://wowi.pastey.net/2144-47xe developted by
 * cladhaire and Tem in #wowi-lounge on irc.freenode.net
]]
local function tokenize(str, s)
	local s,e = s or 0
	local txt = string.sub(str, s)
	local qstart, qend, qtype, quote = string.find(txt, "(['`\"])(.-)%1")
	local tstart, tend, token = string.find(txt, "([^%s]+)")
			
	if quote and token then
		if qstart == tstart or qstart < tstart then 
			s = s + qend
			return quote, tokenize(str, s)
		else
			s = s + tend + 1
			return token, tokenize(str, s)
		end
	elseif quote or token then
		s = s + (qend or tend) + 1
		return (quote or token), tokenize(str, s)
	else
		return nil
	end
end

MapLib.ChatHandler.SlashHandler = function(command, ...)
	if (not command) then
		MapLib.ChatHandler.PrintToChat(L["Please type '/mn help' for a listing of all commands."]);
		return;
	end;
--~ 	DevTools_Dump({...});
	-- search through all registered commands
	command = strlower(command);
	if (MapLib.ChatHandler.registeredCommands[command]) then
		MapLib.ChatHandler.registeredCommands[command].callback(...);
		return;
	end;
	-- command wasn't in the list
	MapLib.ChatHandler.PrintToChat(L["Command not found! Please type '/mn help' for a listing of all commands."]);
end;

MapLib.ChatHandler.RegisterSlashCommand = function(command, callback, helptext)
	MapLib.ChatHandler.registeredCommands[command] = {
		callback = callback,
		helptext = helptext,
	};
end;

MapLib.ChatHandler.PrintHelp = function()
	-- built an alphabetically ordered list
	local list = {};
	local function getnextcommand(list, iterator)
		iterator = iterator + 1;
		if (iterator > #list) then return; else
			return list[iterator], MapLib.ChatHandler.registeredCommands[list[iterator]].helptext, "\n", getnextcommand(list, iterator);
		end;
	end;
	for command, _ in pairs(MapLib.ChatHandler.registeredCommands) do
		tinsert(list, command);
	end;
	table.sort(list);
	MapLib.ChatHandler.PrintToChat(strjoin("", L["Slash commands:\n"], getnextcommand(list, 0)));
end;

-- _SLASH because using the ID twice without setting at least something else causes an error
-- but also automatically changes color and front of the editbox so it might
-- be nice to look into this.
SlashCmdList["MAPNOTES_SLASH"] = function(msg) MapLib.ChatHandler.SlashHandler(tokenize(msg)) end;
SLASH_MAPNOTES_SLASH1 = L["/mn"];
SLASH_MAPNOTES_SLASH2 = L["/mapnotes"];